﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

#endregion

namespace ScrumTable.Common.Text
{
    /// <summary>
    /// Represents a parser for ini values syntax as follwos: {Value1}, {Value2}, {ValueN}
    /// </summary>
    /// <remarks>
    /// All public members MUST be multithreading safe because of the Default
    /// instance property.
    /// </remarks>
    public class ValueParser
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        /// <summary>
        /// Gets the default value parser instance.
        /// </summary>
        public static readonly ValueParser Default = new ValueParser();

        private static readonly Regex ValueParserExpression = new Regex(@"^({(?<value>[^}]*?)},?\s*)+$", RegexOptions.Multiline | RegexOptions.Compiled);
        
        private const string ValuePatternOpen = "{";
        private const string ValuePatternClose = "}";
        private const string ValuePatternSeparator = ", ";

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new parser instance.
        /// </summary>
        public ValueParser()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Converts the given data dictionary entries into a ini string.
        /// </summary>
        /// <param name="toSerialize">Specifies the data list to serialize.</param>
        /// <returns>Returns the serialized data string.</returns>
        public string ToString(ICollection<string> toSerialize)
        {
            PreCondition.AssertNotNull(toSerialize, "toSerialize");
            StringBuilder stringOutput = new StringBuilder();
            int count = 0;

            foreach (string valueToStore in toSerialize)
            {
                stringOutput.Append(ValuePatternOpen);
                stringOutput.Append(valueToStore);
                stringOutput.Append(ValuePatternClose);

                if (count + 1 < toSerialize.Count)
                {
                    stringOutput.Append(ValuePatternSeparator);
                }
                ++count;
            }
            return stringOutput.ToString();
        }

        /// <summary>
        /// Parses the given string and interprets it as value syntax.
        /// </summary>
        /// <param name="toParse">Specifies the data to parse (deserialize).</param>
        /// <returns>Returns the deserialized data list.</returns>
        public ICollection<string> Parse(string toParse)
        {
            List<string> parsedData = new List<string>();

            foreach (Match dataMatch in ParseString(toParse))
            {
                foreach (Capture dataCapture in dataMatch.Groups["value"].Captures)
                {
                    parsedData.Add(dataCapture.Value);
                }
            }

            if (parsedData.Count == 0)
            {
                parsedData.Add(toParse);
            }
            return parsedData;
        }

        /// <summary>
        /// Parses the given stream and interprets it as value syntax.
        /// </summary>
        /// <param name="toParse">Specifies the data to parse (deserialize).</param>
        /// <returns>Returns the deserialized data list.</returns>
        public ICollection<string> Parse(Stream toParse)
        {
            PreCondition.AssertNotNull(toParse, "toParse");

            using (StreamReader reader = new StreamReader(toParse))
            {
                return Parse(reader.ReadToEnd());
            }
        }

        /// <summary>
        /// Tries to parse the given string to validate and returns true
        /// if the given string to validate is an acceptable value string.
        /// </summary>
        /// <param name="toValidate">Specifies the value string to validate.</param>
        /// <returns>Returns true if the given string to validate is an acceptable value string.</returns>
        public bool IsValueString(string toValidate)
        {
            return (ParseString(toValidate).Count > 0);
        }

        private MatchCollection ParseString(string toParse)
        {
            return ValueParserExpression.Matches(toParse ?? string.Empty);
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}